/*
    Copyright (c) Luo Yongping. THIS SOFTWARE COMES WITH NO WARRANTIES, 
    USE AT YOUR OWN RISKS!
*/

#ifndef __COMMON_H__
#define __COMMON_H__

#include <sys/stat.h>
#include <x86intrin.h>
#include <sys/time.h>
#include <cstdlib>
#include <cstring>
#include <cassert>

const int CACHE_LINE_SIZE = 64;
const long BUFSIZE = ((long) 1 << 32); // 4GB
const int ALIGN_SIZE = 256;

static double seconds()
{
  timeval now;
  gettimeofday(&now, NULL);
  return now.tv_sec + now.tv_usec/1000000.0;
}

static inline long getRandom() {
    unsigned long long seed;
    int ok = __builtin_ia32_rdrand64_step (&seed);
    return seed;
}

static inline bool file_exist(const char *file_path) {
    struct stat buffer;
    return (stat(file_path, &buffer) == 0);
}

static inline off_t file_size(const char *file_path) {
    struct stat buffer;
    stat(file_path, &buffer);
    return buffer.st_size;
}

static inline void mfence() {
    asm volatile("sfence" ::: "memory");
}

static inline void drop_cache() {
    char * tmp_buf = (char *)malloc(1 << 27); // 128 MB
    memset(tmp_buf, 0x5a, (1 << 27));
    free(tmp_buf);
    asm volatile("sfence" ::: "memory");
}

static inline void flush(void *data, int len) {
    char *ptr = (char *)((unsigned long long)data &~(CACHE_LINE_SIZE-1));
    for(; ptr < (char *)data + len; ptr += CACHE_LINE_SIZE) {
        #ifdef CLWB
            _mm_clwb(ptr);
        #elif defined(CLFLUSHOPT)
            _mm_clflushopt(ptr);
        #else
            _mm_clflush(ptr);
        #endif
    }
}

class Bitmap {
private:
    uint8_t * buf;
    long capacity;

public:
    Bitmap(long c) {
        long byte_cnt = c / 8 + 1;
        buf = new uint8_t[byte_cnt];
        memset(buf, 0, byte_cnt);
        capacity = byte_cnt * 8;
    }

    ~Bitmap() {
        delete [] buf;
    }

    inline bool read(int idx) {
        //assert(idx < capacity);
        return (buf[idx / 8] & (0x80 >> (idx % 8))) > 0;
    }

    void write(int idx) {
        assert(idx < capacity);
        buf[idx / 8] |= (0x80 >> (idx % 8));
    }
};

#endif //__COMMON_H__
